<template>
  <div class="app-container" style="background-color: #ecf0f5;">
    <div style="font-size: 24px;margin-bottom:5px;"> 任务管理</div>
    <a-form :model="queryParams" ref="queryForm" style="height:40px;" size="small" :inline="true" v-show="showSearch">
      <a-row :gutter="24">
        <a-col :span="1">
          <a-tag
            style="border-radius: 0px;line-height:30px;background-color: #FFF;margin-top: 3px;font-size: 14px;">执行器</a-tag>
        </a-col>
        <a-col :span="4">
          <a-form-item prop="jobGroup" :labelCol="{ span: 4 }" :wrapperCol="{ span: 18, offset: 2 }">
            <a-select v-model="queryParams.jobGroup" placeholder="请选择" clearable @keyup.enter.native="handleQuery">
              <a-select-option v-for="item in actuator_options" :key="item.value" :label="item.label" :value="item.value">
                {{ item.label }}
              </a-select-option>
            </a-select>
          </a-form-item>
        </a-col>
        <a-col :span="2">
          <a-form-item prop="triggerStatus">
            <a-select v-model="queryParams.triggerStatus" placeholder="请选择" clearable @keyup.enter.native="handleQuery">
              <a-select-option v-for="item in status_options" :key="item.value" :label="item.label" :value="item.value">
                {{ showBindStatus(item.value) }}
              </a-select-option>
            </a-select>
          </a-form-item>
        </a-col>
        <a-col :span="3">

          <a-form-item prop="jobDesc">
            <a-input v-model="queryParams.jobDesc" placeholder="请输入任务描述" clearable @keyup.enter.native="handleQuery" />
          </a-form-item>
        </a-col>
        <a-col :span="3">
          <a-form-item prop="executorHandler">
            <a-input v-model="queryParams.executorHandler" placeholder="请输入JobHandler" clearable
              @keyup.enter.native="handleQuery" />
          </a-form-item>
        </a-col>
        <a-col :span="3">
          <a-form-item prop="author">
            <a-input v-model="queryParams.author" placeholder="请输入负责人" clearable @keyup.enter.native="handleQuery" />
          </a-form-item>
        </a-col>
        <a-col :span="2">
          <a-form-item>
            <a-button type="primary" icon="search" style="background-color: #3fc4f8;" @click="handleQuery">搜索</a-button>

          </a-form-item>
        </a-col>
        <a-col :span="2">
          <a-form-item>
            <a-button type="primary" plain icon="plus" @click="handleAdd" v-hasPermi="['xxl-job:info:add']"
              style="background-color: rgb(21, 163, 21);color: white;">新增</a-button>
          </a-form-item>
        </a-col>
      </a-row>
    </a-form>
    <!--加个card包裹起来-->
    <a-card>
      <!--select控制一个页面展示多少条-->
      <div>每页
        <a-select default-value=10 style="width: 120px" @change="handlePageSizeChange">
          <a-select-option value=10>
            10
          </a-select-option>
          <a-select-option value=20>
            20
          </a-select-option>
          <a-select-option value=30>
            30
          </a-select-option>
          <a-select-option value=50>
            50
          </a-select-option>
          <a-select-option value=100>
            100
          </a-select-option>
        </a-select>
        条记录
      </div>
      <!-- 展示内容表格主体 -->
      <a-table v-loading="loading" :columns="columns" :dataSource="infoList" :scroll="{ y: getTableHeight() }"
        :pagination="false" :rowKey="(record, index) => { return index }">
        <span slot="scheduleInfo" slot-scope="text, record">
          {{ record.scheduleType }}{{ scheduleTypeJudge(record.scheduleType) }}{{ record.scheduleConf }}
        </span>
        <span slot="executorInfo" slot-scope="text, record">
          {{ glueTypeTran(record.glueType) }}{{ glueTypeJudge(record.glueType) }}{{ record.executorHandler }}
        </span>
        <span slot="tags" slot-scope="tags">
          <a-tag :key="tags" :color="tags === 0 ? '#d3d4d6' : 'rgb(21, 163, 21)'"
            :style="{ color: tags === 0 ? 'black' : 'white' }">
            <strong>{{ getStatus(tags) }}</strong>
          </a-tag>
        </span>
        <span slot="action" slot-scope="text, record,index">
          <a-dropdown-button class="dropdown_btn">操作
            <a-menu slot="overlay" @click="handleCommand($event, record, index)">
              <a-menu-item key="run_once"> 执行一次 </a-menu-item>
              <a-menu-item key="search_log"> 查询日志 </a-menu-item>
              <a-menu-item key="signup_ip"> 注册节点 </a-menu-item>
              <a-menu-item key="next_runtime" v-if="record.scheduleType !== 'NONE'"> 下次执行时间 </a-menu-item>
              <a-menu-divider v-if="record.glueType !== 'BEAN'" />
              <a-menu-item key="glue_ide" v-if="record.glueType !== 'BEAN'">GLUE IDE</a-menu-item>
              <a-menu-divider />
              <a-menu-item key="open"> {{ getBindStatus(record.triggerStatus) }}</a-menu-item>
              <a-menu-item key="edit"> 编辑 </a-menu-item>
              <a-menu-item key="del"> 删除 </a-menu-item>
              <a-menu-item key="copy"> 复制 </a-menu-item>
            </a-menu>
            <a-icon slot="icon" type="down" />
          </a-dropdown-button>
        </span>
      </a-table>

      <!--Modal展示下次执行时间-->
      <a-modal v-model="isModalOpen" title="下次执行时间" ok-text="确认" cancel-text="取消" centered @ok="hideModal">
        <strong>
          <p> {{ nextTime[0] }}</p>
          <p> {{ nextTime[1] }}</p>
          <p> {{ nextTime[2] }}</p>
          <p> {{ nextTime[3] }}</p>
          <p> {{ nextTime[4] }}</p>
        </strong>
      </a-modal>

      <!--pagination-->
      <a-pagination v-model="pagination.current" :item-render="pagination.itemRender" :total="pagination.total"
        :page-size="pagination.pageSize"
        :show-total="(total) => `共 ${total} 条（总共${Math.ceil(total / this.pagination.pageSize)}页, ${total} 条记录）`"
        :page-size-options="pagination.pageSizeOptions" @change="handlePageChange">
      </a-pagination>
    </a-card>

    <!-- 添加执行一次对话框 -->
    <a-modal :zIndex="1001" :title="title" v-model:visible="open_once" width="90%" :confirm-loading="confirmLoading">
      <a-form-model ref="form_once" :model="form" :rules="rules_once">
        <a-row>执行一次</a-row>
        <hr>
        <a-row :gutter="32">
          <a-col>
            <a-form-model-item label="任务参数" prop="executorParam">
              <a-input v-model:value="form.executorParam" placeholder="请输入任务参数" />
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row :gutter="32">
          <a-col>
            <a-form-model-item label="机器地址" prop="addressList">
              <a-input v-model:value="addressList" placeholder="请输入本次执行的机器地址，为空则从执行器获取" />
            </a-form-model-item>
          </a-col>
        </a-row>
      </a-form-model>
      <div slot="footer" class="dialog-footer">
        <a-button type="primary" @click="submitTriggerForm">保 存</a-button>
        <a-button @click="cancel">取 消</a-button>
      </div>
    </a-modal>

    <!-- 打开GLUE在线编辑器 -->
    <a-modal :zIndex="1001" title="GLUE IDE在线编辑器" v-model:visible="openGlue" width="100%" :footer="null"
      wrapClassName="full-modal">
      <GlueIde ref="glueIde" :glueCodeList="glueCodeList" :showIde="openGlue" @showChange="$event => showChange()"
        @copeChange="$event => copeChange()" />
    </a-modal>

    <!-- 添加或修改任务管理对话框 -->
    <a-modal :zIndex="1001" :title="title" v-model:visible="open" width="70%" :confirm-loading="confirmLoading"
      :footer="null">
      <a-form-model ref="form" :model="form" :rules="rules">
        <a-row>基础配置</a-row>
        <hr>
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="执行器" prop="jobGroup">
              <a-select v-model:value="form.jobGroup">
                <a-select-option v-for="item in actuator_options" :key="item.value" :value="item.value">
                  {{ item.label }}
                </a-select-option>
              </a-select>
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="任务描述" prop="jobDesc">
              <a-input v-model:value="form.jobDesc" placeholder="请输入任务描述" />
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="负责人" prop="author">
              <a-input v-model:value="form.author" placeholder="请输入负责人" />
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="报警邮件" prop="alarmEmail">
              <a-input v-model:value="form.alarmEmail" placeholder="请输入报警邮件，多个邮件地址则逗号分开" />
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row>调度配置</a-row>
        <hr>
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="调度类型" prop="scheduleType">
              <a-select v-model:value="form.scheduleType">
                <a-select-option value="NONE">无</a-select-option>
                <a-select-option value="CRON">CRON</a-select-option>
              </a-select>
            </a-form-model-item>
          </a-col>
          <a-col :span="12" v-if="form.scheduleType === 'CRON'">
            <a-form-model-item label="Cron" prop="scheduleConf">
              <template>
                <a-popover placement="bottom" trigger="click" v-model="visiblepop">
                  <a-input v-model="form.scheduleConf" placeholder="Cron表达式" />
                  <template slot="content">
                    <a-tabs type="border-card">
                      <a-tab-pane key="1" tab="秒" v-if="shouldHide('second')">
                        <CrontabSecond @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj"
                          ref="cronsecond" />
                      </a-tab-pane>

                      <a-tab-pane key="2" tab="分钟" v-if="shouldHide('min')">
                        <CrontabMin @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj"
                          ref="cronmin" />
                      </a-tab-pane>

                      <a-tab-pane key="3" tab="小时" v-if="shouldHide('hour')">
                        <CrontabHour @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj"
                          ref="cronhour" />
                      </a-tab-pane>

                      <a-tab-pane key="4" tab="日" v-if="shouldHide('day')">
                        <CrontabDay @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj"
                          ref="cronday" />
                      </a-tab-pane>

                      <a-tab-pane key="5" tab="月" v-if="shouldHide('month')">
                        <CrontabMonth @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj"
                          ref="cronmonth" />
                      </a-tab-pane>

                      <a-tab-pane key="6" tab="周" v-if="shouldHide('week')">
                        <CrontabWeek @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj"
                          ref="cronweek" />
                      </a-tab-pane>

                      <a-tab-pane key="7" tab="年" v-if="shouldHide('year')">
                        <CrontabYear @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj"
                          ref="cronyear" />
                      </a-tab-pane>
                    </a-tabs>
                    <CrontabResult ref="crontabResult" :ex="crontabValueString" />
                    <div slot="footer" class="pop_btn">
                      <a-button type="primary" @click="submitFill">确定</a-button>
                      <a-button type="warning" @click="clearCron">重置</a-button>
                      <a-button @click="hidePop">取消</a-button>
                    </div>
                  </template>
                </a-popover>
              </template>
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row>任务配置</a-row>
        <hr>
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="运行模式" prop="glueType">
              <a-select v-model:value="form.glueType">
                <a-select-option value="BEAN">BEAN</a-select-option>
                <a-select-option value="GLUE_GROOVY">GLUE(Java)</a-select-option>
                <a-select-option value="GLUE_SHELL">GLUE(Shell)</a-select-option>
                <a-select-option value="GLUE_PYTHON">GLUE(Python)</a-select-option>
                <a-select-option value="GLUE_PHP">GLUE(PHP)</a-select-option>
                <a-select-option value="GLUE_NODEJS">GLUE(Nodejs)</a-select-option>
                <a-select-option value="GLUE_POWERSHELL">GLUE(PowerShell)</a-select-option>
              </a-select>
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="JobHandler" prop="executorHandler" v-if="form.glueType !== 'BEAN'">
              <a-input v-model="form.executorHandler" placeholder="请输入JobHandler" maxLength="100" :disabled=true
                allow-clear />
            </a-form-model-item>
            <a-form-model-item label="JobHandler" prop="executorHandler" v-if="form.glueType === 'BEAN'">
              <a-input v-model="form.executorHandler" placeholder="请输入JobHandler" maxLength="100" :disabled=false
                allow-clear />
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-form-model-item label="任务参数" prop="executorParam">
          <a-textarea v-model:value="form.executorParam" placeholder="请输入任务参数" />
        </a-form-model-item>
        <a-row>高级配置</a-row>
        <hr>
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="路由策略" prop="executorRouteStrategy">
              <a-select v-model:value="form.executorRouteStrategy">
                <a-select-option value="FIRST">第一个</a-select-option>
                <a-select-option value="LAST">最后一个</a-select-option>
                <a-select-option value="ROUND">轮询</a-select-option>
                <a-select-option value="RANDOM">随机</a-select-option>
                <a-select-option value="CONSISTENT_HASH">一致性HASH</a-select-option>
                <a-select-option value="LEAST_FREQUENTLY_USED">最不经常使用</a-select-option>
                <a-select-option value="LEAST_RECENTLY_USED">最近最久未使用</a-select-option>
                <a-select-option value="FAILOVER">故障转移</a-select-option>
                <a-select-option value="BUSYOVER">忙碌转移</a-select-option>
                <a-select-option value="SHARDING_BROADCAST">分片广播</a-select-option>
              </a-select>
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="子任务ID" prop="childJobid">
              <a-input v-model:value="form.childJobid" placeholder="请输入子任务的任务ID，若存在多个则逗号分开" />
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="调度过期策略" prop="misfireStrategy">
              <a-select v-model:value="form.misfireStrategy">
                <a-select-option value="DO_NOTHING">忽略</a-select-option>
                <a-select-option value="FIRE_ONCE_NOW">立即执行一次</a-select-option>
              </a-select>
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="阻塞处理策略" prop="executorBlockStrategy">
              <a-select v-model:value="form.executorBlockStrategy">
                <a-select-option value="SERIAL_EXECUTION">单机串行</a-select-option>
                <a-select-option value="DISCARD_LATER">丢弃后续调度</a-select-option>
                <a-select-option value="COVER_EARLY">覆盖之前调度</a-select-option>
              </a-select>
            </a-form-model-item>
          </a-col>
        </a-row>
        <a-row :gutter="32">
          <a-col :span="12">
            <a-form-model-item label="任务超时时间" prop="executorTimeout">
              <a-input v-model:value="form.executorTimeout" placeholder="任务超时时间，单位秒，大于零时生效" maxLength="6" allow-clear />
            </a-form-model-item>
          </a-col>
          <a-col :span="12">
            <a-form-model-item label="失败重试次数" prop="executorFailRetryCount">
              <a-input v-model:value="form.executorFailRetryCount" placeholder="失败重试次数，大于零时生效" maxLength="4"
                allow-clear />
            </a-form-model-item>
          </a-col>
        </a-row>
      </a-form-model>
      <div class="dialog-footer">
        <a-button type="primary" @click="submitForm">保 存</a-button>
        <a-button @click="cancel">取 消</a-button>
      </div>
    </a-modal>
  </div>
</template>

<script>
import { listInfo, getInfo, delInfo, addInfo, updateInfo, openInfo, stopInfo, nextInfo, triggerInfo, getCodeInfo, saveCodeInfo } from "@/api/xxl-job/info";
import { listGroup } from "@/api/xxl-job/group";
import CrontabSecond from "./components/second.vue";
import CrontabMin from "./components/min.vue";
import CrontabHour from "./components/hour.vue";
import CrontabDay from "./components/day.vue";
import CrontabMonth from "./components/month.vue";
import CrontabWeek from "./components/week.vue";
import CrontabYear from "./components/year.vue";
import CrontabResult from "./components/results.vue";
import GlueIde from "./components/glueIDE.vue";

export default {
  name: "AntDesignInfo",
  props: ["expression", "hideComponent"],
  data() {
    // 表单校验数据类型
    const isNum = (rule, value, callback) => { // 参数顺序必须如
      let reg = /^[0-9]{1,6}$/;
      if (reg.test(value)) {
        callback()
      } else {
        callback(new Error("必须为整数"))
      }
    }
    const isEmail = (rule, value, callback) => {
      let reg = /^\w{1,18}@[a-z0-9]+(\.[a-z]{2,4})+$/i;
      if (reg.test(value)) {
        callback()
      } else if (value == null) {
        callback()
      } else {
        callback(new Error("必须符合邮箱格式"))
      }
    }

    return {
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 任务管理表格数据
      infoList: [],
      // 获取的执行器数据
      grouplist: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      open_once: false,
      isModalOpen: false,
      addressList: null,
      confirmLoading: false,
      //下次执行时间
      nextTime: [],
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        jobGroup: null,
        jobDesc: null,
        addTime: null,
        author: null,
        alarmEmail: null,
        scheduleType: null,
        scheduleConf: null,
        misfireStrategy: null,
        executorRouteStrategy: null,
        executorHandler: null,
        executorParam: null,
        executorBlockStrategy: null,
        executorTimeout: null,
        executorFailRetryCount: null,
        glueType: null,
        glueSource: null,
        glueRemark: null,
        glueUpdatetime: null,
        childJobid: null,
        triggerStatus: null,
        triggerLastTime: null,
        triggerNextTime: null
      },
      //表格内容
      columns: [{
        title: '任务ID',
        dataIndex: 'id',
        align: "center",
        width: "10%",
        sorter: (a, b) => {
          return a.id - b.id
        },
        defaultSortOrder: 'ascend',
      },
      {
        title: '任务描述',
        dataIndex: 'jobDesc',
        key: 'jobDesc',
        align: "center",
        width: "10%",
      },
      {
        title: '调度类型',
        dataIndex: 'scheduleInfo',
        key: 'scheduleInfo',
        align: "center",
        scopedSlots: { customRender: 'scheduleInfo' },
        width: "20%",
      },
      {
        title: '运行模式',
        dataIndex: 'executorInfo',
        key: 'executorInfo',
        align: "center",
        scopedSlots: { customRender: 'executorInfo' },
        width: "20%",
      },
      {
        title: '负责人',
        dataIndex: 'author',
        align: "center",
        key: 'author',
        width: "10%",
      },
      {
        title: '状态',
        dataIndex: 'triggerStatus',
        key: 'triggerStatus',
        align: "center",
        scopedSlots: { customRender: 'tags' },
        width: "10%",
      },
      {
        title: '操作',
        align: "center",
        scopedSlots: { customRender: 'action' },
        width: "10%",
      }],
      //pagination分页参数
      pagination: ({
        pageSize: 10, // 每页显示的条数
        showQuickJumper: false, // 是否可以快速跳转到指定页
        current: 1, // 当前页数
        total: 50, // 总条数
        itemRender(current, type, originalElement) {
          if (type === 'prev') {
            return <div style="padding-left:850px"><a>上页</a></div>;
          } else if (type === 'next') {
            return <a>下页</a>;
          }
          return originalElement;
        },
      }),
      // 表单参数
      form: {},
      status_options: [
        {
          value: '',
        },
        {
          value: '0',
        },
        {
          value: '1',
        }],
      actuator_options: [],
      // 表单校验
      rules: {
        jobGroup: [
          { required: true, message: "执行器主键ID不能为空", trigger: "blur" }
        ],
        jobDesc: [
          { required: true, message: "任务描述不能为空", trigger: "blur" }
        ],
        scheduleType: [
          { required: true, message: "调度类型不能为空", trigger: "change" }
        ],
        scheduleConf: [
          { required: true, message: "CRON表达式不能为空", trigger: "blur" }
        ],
        misfireStrategy: [
          { required: true, message: "调度过期策略不能为空", trigger: "blur" }
        ],
        executorTimeout: [
          { required: true, message: "任务执行超时时间，单位秒不能为空", trigger: "blur" },
          { validator: isNum, message: "任务执行超时时间必须为小于七位的正整数", trigger: 'blur' }
        ],
        executorFailRetryCount: [
          { required: true, message: "失败重试次数不能为空", trigger: "blur" },
          { validator: isNum, message: "失败重试次数必须为小于五位的正整数", trigger: 'blur' }
        ],
        glueType: [
          { required: true, message: "GLUE类型不能为空", trigger: "change" }
        ],
        author: [
          { required: true, message: "负责人不能为空", trigger: "blur" }
        ],
        executorRouteStrategy: [
          { required: true, message: "路由策略不能为空", trigger: "blur" }
        ],
        executorBlockStrategy: [
          { required: true, message: "阻塞处理策略不能为空", trigger: "blur" }
        ],
        alarmEmail: [
          { validator: isEmail, message: "请输入正确的邮箱" }
        ]
      },
      rules_once: {

      },
      tabTitles: ["秒", "分钟", "小时", "日", "月", "周", "年"],
      tabActive: 0,
      myindex: 0,
      visiblepop: false,
      openGlue: false,
      codeGlueType: null,
      codeList: {
        id: null,
        jobId: null,
        glueType: null,
        glueSource: null,
        glueRemark: null,
        addTime: null,
        updateTime: null
      },
      codeParams: {
        id: null,
        jobId: null,
        glueType: null,
        glueSource: null,
        glueRemark: null,
        addTime: null,
        updateTime: null
      },
      glueCodeList: [],
      crontabValueObj: {
        second: "*",
        min: "*",
        hour: "*",
        day: "*",
        month: "*",
        week: "?",
        year: ""
      }
    };
  },
  created() {
    this.getList();
    this.getGroup();
    this.queryParams.triggerStatus = this.status_options[0].value
  },
  mount() {
    this.getGroup()
  },
  methods: {
    /** 查询任务管理列表 */
    getList() {
      this.loading = true;
      listInfo(this.queryParams).then(response => {
        this.infoList = response.rows;
        this.pagination.total = response.total;
        this.loading = false;
      });
    },
    // 获取执行器数据
    getGroup() {
      this.loading = true;
      listGroup(this.queryParams).then(response => {
        this.groupList = response.rows;
        for (let item in this.groupList) {
          this.actuator_options.push({
            value: this.groupList[item].id,
            label: this.groupList[item].title
          })
        }
        this.queryParams.jobGroup = this.actuator_options[0].value;
        this.loading = false;
      });
    },
    // 取消按钮
    cancel() {
      this.open = false;
      this.open_once = false;
      this.reset();
    },
    // 表单重置
    reset() {
      this.form = {
        id: null,
        jobGroup: null,
        jobDesc: null,
        addTime: null,
        updateTime: null,
        author: null,
        alarmEmail: null,
        scheduleType: null,
        scheduleConf: null,
        misfireStrategy: null,
        executorRouteStrategy: null,
        executorHandler: null,
        executorParam: null,
        executorBlockStrategy: null,
        executorTimeout: null,
        executorFailRetryCount: null,
        glueType: null,
        glueSource: null,
        glueRemark: null,
        glueUpdatetime: null,
        childJobid: null,
        triggerStatus: null,
        triggerLastTime: null,
        triggerNextTime: null
      };
      this.resetForm("form");
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset();
      this.form.glueType = 'BEAN';
      this.open = true;
      this.title = "添加任务管理";
    },
    /** 修改按钮操作 */
    handleUpdate(row) {
      this.reset();
      const id = row.id || this.ids
      getInfo(id).then(response => {
        this.form = response.data;
        this.open = true;
        this.title = "修改任务管理";
      });
    },
    /** 提交按钮 */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          if (this.form.scheduleType == 'NONE') {
            this.form.scheduleConf = null
          }
          if (this.form.id != null) {
            updateInfo(this.form).then(response => {
              this.$modal.msgSuccess("修改成功");
              this.open = false;
              this.getList();
            });
          } else {
            this.initCode();
            addInfo(this.form).then(response => {
              this.$modal.msgSuccess("新增成功");
              this.open = false;
              this.getList();
            });
          }
        }
      });
    },
    /** 执行一次提交按钮 */
    submitTriggerForm() {
      this.$refs["form_once"].validate(valid => {
        if (valid) {
          triggerInfo(this.form.id, this.form.executorParam, this.addressList).then(response => {
            this.open_once = false;
            this.reset();
          })
        }
      });
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const ids = row.id || this.ids;
      this.$modal.confirm('是否确认删除任务管理编号为"' + ids + '"的数据项？').then(function() {
        return delInfo(ids);
      }).then(() => {
        this.getList();
        this.$modal.msgSuccess("删除成功");
      }).catch(() => { });
    },
    /** 导出按钮操作 */
    handleExport() {
      this.download('xxl-job/info/export', {
        ...this.queryParams
      }, `info_${new Date().getTime()}.xlsx`)
    },
    /**select时展示状态中文 */
    showBindStatus(status) {
      if (status == "0") {
        status = '停止'
      }
      else if (status == "1") {
        status = '启动'
      }
      else status = '全部'
      return status
    },
    /**获取状态绑定数据 */
    getBindStatus(status) {
      if (status == "0") {
        status = '启动'
      }
      else {
        status = '停止'
      }
      return status
    },
    /**状态栏展示数据 */
    getStatus(status) {
      if (status == "1") {
        status = 'RUNNING'
      }
      else {
        status = 'STOP'
      }
      return status
    },
    /**根据当前窗口高度动态设置el-table的显示宽度 上方200 下方60 card多加70*/
    getTableHeight() {
      return (window.innerHeight - 340)
    },
    /** 是否显示冒号判断*/
    glueTypeJudge(type) {
      if (type == 'BEAN') {
        return ':'
      }
      else return ''
    },
    scheduleTypeJudge(type) {
      if (type != 'NONE') {
        return ':'
      }
      else return ''
    },
    // glueTpye类型转换
    glueTypeTran(type) {
      if (type == 'BEAN') {
        return 'BEAN'
      } else if (type == 'GLUE_GROOVY') {
        return 'GLUE(Java)'
      } else if (type == 'GLUE_SHELL') {
        return 'GLUE(Shell)'
      } else if (type == 'GLUE_PYTHON') {
        return 'GLUE(Python)'
      } else if (type == 'GLUE_PHP') {
        return 'GLUE(PHP)'
      } else if (type == 'GLUE_NODEJS') {
        return 'GLUE(Nodejs)'
      } else if (type == 'GLUE_POWERSHELL') {
        return 'GLUE(PowerShell)'
      }
    },
    /** 下拉栏操作 */
    handleCommand(command, row, index) {
      command = command.key
      if (command == "del") {
        const taskIds = row.id || this.ids;
        this.$modal.confirm('是否确认删除任务管理编号为"' + taskIds + '"的数据项？').then(function() {
          return delInfo(taskIds);
        }).then(() => {
          this.getList();
          this.$modal.msgSuccess("删除成功");
        }).catch(() => { });
      }
      else if (command == "edit") {
        this.reset();
        const taskId = row.id || this.ids
        getInfo(taskId).then(response => {
          this.form = response.data;
          this.open = true;
          this.title = "修改任务管理";
        });
      }
      else if (command == "copy") {
        this.reset();
        const taskId = row.id || this.ids
        getInfo(taskId).then(response => {
          this.form = response.data;
          this.open = true;
          this.form.taskId = null
          this.title = "复制任务管理";
        });
      }
      else if (command == "signup_ip") {
        this.$alert("", "注册节点");
      }
      else if (command == "search_log") {
        this.$router.push({ path: "/xxl-job/log/" });
      }
      else if (command == "open") {
        const taskIds = row.id || this.ids;
        if (row.triggerStatus == 0) {
          openInfo(taskIds).then(response => {
            this.getList();
          })
        }
        else {
          stopInfo(taskIds).then(response => {
            this.getList();
          })
        }
      }
      else if (command == "next_runtime") {
        const taskIds = row.id || this.ids;
        nextInfo(taskIds).then(response => {
          this.isModalOpen = true;
          this.nextTime = response.data
          console.log(response.data)
        })
      }
      else if (command == "run_once") {
        this.reset();
        const taskIds = row.id || this.ids;
        this.form.id = taskIds
        this.open_once = true;
      }
      else if (command == 'glue_ide') {
        this.codeParams.jobId = row.id
        this.codeGlueType = row.glueType
        getCodeInfo(this.codeParams).then(response => {
          const codeLists = response.data
          if (codeLists[0] == null) {
            this.glueCodeList.push({
              jobId: this.codeParams.jobId,
              glueType: this.codeGlueType
            })
          } else {
            for (let item in codeLists) {
              this.glueCodeList.push(codeLists[item])
            }
          }
          this.openGlue = true
        })
      }
      else {
        this.$message('click on item ' + command);
      }
    },
    /** 页码改变时的处理函数*/
    handlePageChange(page, pageSize) {
      this.queryParams.pageNum = page
      this.pagination.current = page
      this.getList()
    },
    /** 页码改变时的处理函数*/
    handlePageSizeChange(page) {
      this.queryParams.pageSize = page
      this.pagination.pageSize = page
      this.getList()
    },
    /**Modal关闭控制 */
    hideModal() {
      this.isModalOpen = false
    },


    // 初始源码生成
    initCode() {
      if (this.form.glueType === 'GLUE_GROOVY') {
        this.form.glueSource = `
package com.xxl.job.service.handler;

import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.IJobHandler;

public class DemoGlueJobHandler extends IJobHandler {

	@Override
	public void execute() throws Exception {
		XxlJobHelper.log("XXL-JOB, Hello World.");
	}

}
        `
      } else if (this.form.glueType === 'GLUE_SHELL') {
        this.form.glueSource = `
#!/bin/bash
echo "xxl-job: hello shell"

echo "脚本位置：$0"
echo "任务参数：$1"
echo "分片序号 = $2"
echo "分片总数 = $3"

echo "Good bye!"
exit 0
        `
      } else if (this.form.glueType === 'GLUE_PYTHON') {
        this.form.glueSource = `
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time
import sys

print "xxl-job: hello python"

print "脚本位置：", sys.argv[0]
print "任务参数：", sys.argv[1]
print "分片序号：", sys.argv[2]
print "分片总数：", sys.argv[3]

print "Good bye!"
exit(0)
        `
      } else if (this.form.glueType === 'GLUE_PHP') {
        this.form.glueSource = String.raw`
&lt?php

echo "xxl-job: hello php  \n";

echo "脚本位置：$argv[0]  \n";
echo "任务参数：$argv[1]  \n";
echo "分片序号 = $argv[2]  \n";
echo "分片总数 = $argv[3]  \n";

echo "Good bye!  \n";
exit(0);

?&gt
        `
      } else if (this.form.glueType === 'GLUE_NODEJS') {
        this.form.glueSource = `
#!/usr/bin/env node
console.log("xxl-job: hello nodejs")

var arguments = process.argv

console.log("脚本位置: " + arguments[1])
console.log("任务参数: " + arguments[2])
console.log("分片序号: " + arguments[3])
console.log("分片总数: " + arguments[4])

console.log("Good bye!")
process.exit(0)
        `
      } else if (this.form.glueType === 'GLUE_POWERSHELL') {
        this.form.glueSource = `
Write-Host "xxl-job: hello powershell"

Write-Host "脚本位置: " $MyInvocation.MyCommand.Definition
Write-Host "任务参数: "
	if ($args.Count -gt 2) { $args[0..($args.Count-3)] }
Write-Host "分片序号: " $args[$args.Count-2]
Write-Host "分片总数: " $args[$args.Count-1]

Write-Host "Good bye!"
exit 0
        `
      }
    },
    // GLUE编辑器传值
    showChange() {
      this.glueCodeList = []
      this.openGlue = this.$refs.glueIde.getShow()
    },
    copeChange() {
      this.codeList.jobId = this.codeParams.jobId
      this.codeList.glueSource = this.$refs.glueIde.getCode()
      this.codeList.glueRemark = this.$refs.glueIde.getRemark()
      const code = this.codeList.glueSource.replace(/</g, '&lt')
      this.codeList.glueSource = code.replace(/>/g, '&gt')
      saveCodeInfo(this.codeList).then(response => {
        this.$modal.msgSuccess("源码保存成功")
      })
    },


    shouldHide(key) {
      if (this.hideComponent && this.hideComponent.includes(key)) return false;
      return true;
    },
    resolveExp() {
      // 反解析 表达式
      if (this.expression) {
        let arr = this.expression.split(" ");
        if (arr.length >= 6) {
          //6 位以上是合法表达式
          let obj = {
            second: arr[0],
            min: arr[1],
            hour: arr[2],
            day: arr[3],
            month: arr[4],
            week: arr[5],
            year: arr[6] ? arr[6] : ""
          };
          this.crontabValueObj = {
            ...obj
          };
          for (let i in obj) {
            if (obj[i]) this.changeRadio(i, obj[i]);
          }
        }
      } else {
        // 没有传入的表达式 则还原
        this.clearCron();
      }
    },
    // tab切换值
    tabCheck(index) {
      this.tabActive = index;
    },
    // 由子组件触发，更改表达式组成的字段值
    updateCrontabValue(name, value, from) {
      "updateCrontabValue", name, value, from;
      this.crontabValueObj[name] = value;
      if (from && from !== name) {
        // console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
        this.changeRadio(name, value);
      }
      this.form.scheduleConf = this.valueString();
    },
    // 赋值到组件
    changeRadio(name, value) {
      let arr = ["second", "min", "hour", "month"],
        refName = "cron" + name,
        insValue;

      if (!this.$refs[refName]) return;

      if (arr.includes(name)) {
        if (value === "*") {
          insValue = 1;
        } else if (value.indexOf("-") > -1) {
          let indexArr = value.split("-");
          isNaN(indexArr[0])
            ? (this.$refs[refName].cycle01 = 0)
            : (this.$refs[refName].cycle01 = indexArr[0]);
          this.$refs[refName].cycle02 = indexArr[1];
          insValue = 2;
        } else if (value.indexOf("/") > -1) {
          let indexArr = value.split("/");
          isNaN(indexArr[0])
            ? (this.$refs[refName].average01 = 0)
            : (this.$refs[refName].average01 = indexArr[0]);
          this.$refs[refName].average02 = indexArr[1];
          insValue = 3;
        } else {
          insValue = 4;
          this.$refs[refName].checkboxList = value.split(",");
        }
      } else if (name == "day") {
        if (value === "*") {
          insValue = 1;
        } else if (value == "?") {
          insValue = 2;
        } else if (value.indexOf("-") > -1) {
          let indexArr = value.split("-");
          isNaN(indexArr[0])
            ? (this.$refs[refName].cycle01 = 0)
            : (this.$refs[refName].cycle01 = indexArr[0]);
          this.$refs[refName].cycle02 = indexArr[1];
          insValue = 3;
        } else if (value.indexOf("/") > -1) {
          let indexArr = value.split("/");
          isNaN(indexArr[0])
            ? (this.$refs[refName].average01 = 0)
            : (this.$refs[refName].average01 = indexArr[0]);
          this.$refs[refName].average02 = indexArr[1];
          insValue = 4;
        } else if (value.indexOf("W") > -1) {
          let indexArr = value.split("W");
          isNaN(indexArr[0])
            ? (this.$refs[refName].workday = 0)
            : (this.$refs[refName].workday = indexArr[0]);
          insValue = 5;
        } else if (value === "L") {
          insValue = 6;
        } else {
          this.$refs[refName].checkboxList = value.split(",");
          insValue = 7;
        }
      } else if (name == "week") {
        if (value === "*") {
          insValue = 1;
        } else if (value == "?") {
          insValue = 2;
        } else if (value.indexOf("-") > -1) {
          let indexArr = value.split("-");
          isNaN(indexArr[0])
            ? (this.$refs[refName].cycle01 = 0)
            : (this.$refs[refName].cycle01 = indexArr[0]);
          this.$refs[refName].cycle02 = indexArr[1];
          insValue = 3;
        } else if (value.indexOf("#") > -1) {
          let indexArr = value.split("#");
          isNaN(indexArr[0])
            ? (this.$refs[refName].average01 = 1)
            : (this.$refs[refName].average01 = indexArr[0]);
          this.$refs[refName].average02 = indexArr[1];
          insValue = 4;
        } else if (value.indexOf("L") > -1) {
          let indexArr = value.split("L");
          isNaN(indexArr[0])
            ? (this.$refs[refName].weekday = 1)
            : (this.$refs[refName].weekday = indexArr[0]);
          insValue = 5;
        } else {
          this.$refs[refName].checkboxList = value.split(",");
          insValue = 6;
        }
      } else if (name == "year") {
        if (value == "") {
          insValue = 1;
        } else if (value == "*") {
          insValue = 2;
        } else if (value.indexOf("-") > -1) {
          insValue = 3;
        } else if (value.indexOf("/") > -1) {
          insValue = 4;
        } else {
          this.$refs[refName].checkboxList = value.split(",");
          insValue = 5;
        }
      }
      this.$refs[refName].radioValue = insValue;
    },
    // 表单选项的子组件校验数字格式（通过-props传递）
    checkNumber(value, minLimit, maxLimit) {
      // 检查必须为整数
      value = Math.floor(value);
      if (value < minLimit) {
        value = minLimit;
      } else if (value > maxLimit) {
        value = maxLimit;
      }
      return value;
    },
    valueString() {
      let obj = this.crontabValueObj;
      let str =
        obj.second +
        " " +
        obj.min +
        " " +
        obj.hour +
        " " +
        obj.day +
        " " +
        obj.month +
        " " +
        obj.week +
        (obj.year == "" ? "" : " " + obj.year);
      return str;
    },
    // 填充表达式
    submitFill() {
      this.form.scheduleConf = this.valueString();
      this.visiblepop = false;
    },
    clearCron() {
      // 还原选择项
      ("准备还原");
      this.crontabValueObj = {
        second: "*",
        min: "*",
        hour: "*",
        day: "*",
        month: "*",
        week: "?",
        year: ""
      };
      for (let j in this.crontabValueObj) {
        this.changeRadio(j, this.crontabValueObj[j]);
      }
      this.form.scheduleConf = this.valueString();
    },
    hidePop() {
      this.visiblepop = false;
    }
  },
  computed: {
    crontabValueString: function() {
      let obj = this.crontabValueObj;
      let str =
        obj.second +
        " " +
        obj.min +
        " " +
        obj.hour +
        " " +
        obj.day +
        " " +
        obj.month +
        " " +
        obj.week +
        (obj.year == "" ? "" : " " + obj.year);
      return str;
    },
  },
  components: {
    CrontabSecond,
    CrontabMin,
    CrontabHour,
    CrontabDay,
    CrontabMonth,
    CrontabWeek,
    CrontabYear,
    CrontabResult,
    GlueIde,
  },
  watch: {
    expression: "resolveExp",
    hideComponent(value) {
      // 隐藏部分组件
    },
    visiblepop(value) {
      if (value === true) {
        this.form.scheduleConf = this.valueString();
      }
    }
  },
  mounted: function() {
    this.resolveExp();
  }
};
</script>
<style scoped>
.pop_btn {
  text-align: center;
  margin-top: 20px;
}

::v-deep .ant-table-thead>tr>th,
.ant-table-tbody>tr>td {
  padding: 8px 8px;
  overflow-wrap: break-word;
}

::v-deep .ant-table-tbody .ant-table-row td {
  padding-top: 8px;
  padding-bottom: 8px;
}
</style>
<style>
.ant-popover {
  height: 400px;
  overflow: auto;
}

.dialog-footer {
  position: sticky;
  bottom: 10px;
  text-align: center;
  background-color: #fff;
}

/* .ant-modal {
  width: 100vw !important;
  max-width: 100vw !important;
  top: 0;
  padding-bottom: 0;
}

.ant-modal-body {
  height: calc(100vh - 55px - 53px);
  overflow-y: auto;
} */
.full-modal .ant-modal {
  width: 100%;
  top: 0;
  padding-bottom: 0;
  margin: 0;
}

.full-modal .ant-modal-content {
  display: flex;
  flex-direction: column;
  height: calc(100vh);
  width: calc(100vw);
}

.full-modal .ant-modal-body {
  flex: 1;
  overflow-y: auto;
}

.ant-pagination li.ant-pagination-item-active {
  background-color: #4b8dcb !important;
}

.ant-pagination li.ant-pagination-item-active a {
  color: white !important;
}

.dropdown_btn button {
  background-color: #4b8dcb;
  color: #fff;
  border: #4b8dcb;
}

.dropdown_btn :hover {
  background-color: #4b8dcb;
  color: #fff;
  border: #4b8dcb;
}

.action_tag {
  color: #000;
  border-radius: 0 !important;
  border-color: #d2d6de !important;
  background-color: #fff !important;
  font-size: 13px;
  height: 100%;
  line-height: 32px;
}
</style>

